{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 第3章 numpy计算\n",
    "NumPy（Numerical Python的简称）是高性能科学计算和数据分析的基础包。部分功能如下：\n",
    "\n",
    "* ndarray，一个具有矢量算术运算和复杂广播能力的快速且节省空间的多维数组。\n",
    "* 用于对整组数据进行快速运算的标准数学函数（无需编写循环）。\n",
    "* 用于读写磁盘数据的工具以及用于操作内存映射文件的工具。\n",
    "* 线性代数、随机数生成以及傅里叶变换功能。\n",
    "* 用于集成由C、C++、Fortran等语言编写的代码的工具。\n",
    "\n",
    "最后一点也是从生态系统角度来看最重要的一点。由于NumPy提供了一个简单易用的C API，因此很容易将数据传递给由低级语言编写的外部库，外部库也能以NumPy数组的形式将数据返回给Python。这个功能使Python成为一种包装C/C++/Fortran历史代码库的选择，并使被包装库拥有一个动态的、易用的接口。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " 本章主要分为以下几个部分进行介绍：\n",
    " \n",
    "一、NumPy的ndarray\n",
    "* 创建ndarray\n",
    "* ndarray的数据类型\n",
    "* ndarray 对象常用方法\n",
    "* 基本的切片与索引\n",
    "* 高级索引\n",
    "* 整数索引\n",
    "* 布尔索引\n",
    "* 花式索引\n",
    "* 按条件返回索引\n",
    "二、通用函数：快速的元素级数组函数\n",
    "* 一元通用函数\n",
    "* 二元通用函数\n",
    "* 执行特定矢量化运算的特殊ufunc方法\n",
    "三、统计方法\n",
    "四、排序\n",
    "五、数据的唯一化和集合运算\n",
    "六、随机数生成\n",
    "七、NumPy 矩阵库(Matrix)及其计算\n",
    "* 创建矩阵\n",
    "* 矩阵运算\n",
    "八、高级数组操作\n",
    "* 反转、转置数组\n",
    "* 数组重塑\n",
    "* 数组的合并和拆分\n",
    "* 数组元素的添加与删除\n",
    "九、广播"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy.matlib \n",
    "import numpy as np\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 一、NumPy的ndarray\n",
    "一种多维数组对象NumPy最重要的一个特点就是其N维数组对象（即ndarray），该对象是一个快速而灵活的大数据集容器。本部分主要介绍ndarray以及基本的切片与索引。"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "ndarray是一系列同类型数据的集合，以 0 下标为开始进行集合中元素的索引。\n",
    "ndarray 对象是用于存放同类型元素的多维数组。ndarray 中的每个元素在内存中都有相同存储大小的区域。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 创建ndarray"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "创建数组最简单的办法就是使用array函数。它接受一切序列型的对象（包括其他数组），然后产生一个新的含有传入数据的NumPy数组。\n",
    "numpy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)\n",
    "参数说明：\n",
    "object：数组或嵌套的数列\n",
    "dtype：数组元素的数据类型，可选\n",
    "copy：对象是否需要复制，可选\n",
    "order：创建数组的样式，C为行方向，F为列方向，A为任意方向（默认）\n",
    "subok：默认返回一个与基类类型一致的数组\n",
    "ndmin：指定生成数组的最小维度\n",
    "一般情况下前两个参数是必须有的，其余参数较少使用。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([6. , 7.5, 8. , 0. , 1. ])"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data1=[6,7.5,8,0,1]\n",
    "arr1=np.array(data1)\n",
    "arr1"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "除此之外还有一些函数也可以创建ndarray\n",
    "从已有数组创建： numpy.asarray(a, dtype = None, order = None)\n",
    "未初始化数组：numpy.empty(shape, dtype = float, order = 'C')\n",
    "全0数组：numpy.zeros(shape, dtype = float, order = 'C')\n",
    "全1数组：numpy.ones(shape, dtype = None, order = 'C')\n",
    "数值范围数组：numpy.arange(start, stop, step, dtype)\n",
    "对角数组：numpy.eye(N, M=None, k=0, dtype=, order='C')\n",
    "其中： \n",
    "shape: 数组形状 \n",
    "dtype: 数据类型\n",
    "order: C和F,分别代表行优先和列优先。 \n",
    "start: 起始值，默认为0 \n",
    "stop: 终止值（不包含） \n",
    "step: 步长，默认为1 \n",
    "dtype: 返回ndarray的数据类型，默认使用输入数据的类型。 \n",
    "num: 要生成的等步长的样本数量，默认为50"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "np.zeros((2,2)):\n",
      " [[0. 0.]\n",
      " [0. 0.]]\n",
      "np.ones((2,2)):\n",
      " [[1. 1.]\n",
      " [1. 1.]]\n",
      "np.eye((2)):\n",
      " [[1. 0.]\n",
      " [0. 1.]]\n",
      "np.random.random((2,2)):\n",
      " [[0.57223409 0.08745789]\n",
      " [0.54097632 0.87183112]]\n"
     ]
    }
   ],
   "source": [
    "print (\"np.zeros((2,2)):\\n\", np.zeros((2,2)))\n",
    "print (\"np.ones((2,2)):\\n\", np.ones((2,2)))\n",
    "print (\"np.eye((2)):\\n\", np.eye((2)))\n",
    "print (\"np.random.random((2,2)):\\n\", np.random.random((2,2)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ndarray的数据类型\n",
    "dtype（数据类型）是一个特殊的对象，它含有ndaray将一块内存解释为特定数据类型所需的信息："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "float64 int32\n"
     ]
    }
   ],
   "source": [
    "arr1=np. array([1,2,3], dtype=np. float64)\n",
    "arr2=np. array([1,2,3], dtype=np. int32)\n",
    "print(arr1.dtype,arr2.dtype)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "int32\n",
      "float64\n"
     ]
    }
   ],
   "source": [
    "#你可以通过ndarray的astype方法显式地转换其dtype\n",
    "arr=np.array([1,2,3,4,5])\n",
    "print(arr.dtype)\n",
    "float_arr=arr.astype(np.float64)\n",
    "print(float_arr.dtype)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ndarray 对象常用方法"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "ndarray.ndim: 秩，即轴的数量或维度的数量\n",
    "ndarray.shape: 数组的维度，对于矩阵，n 行 m 列\n",
    "ndarray.size: 数组元素的总个数，相当于 .shape 中 n*m 的值\n",
    "ndarray.dtype: ndarray 对象的元素类型\n",
    "ndarray.tolist: narray对象转化为list\n",
    "ndarray.newaxis:给原数组增加一个维度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x ndim:  1\n",
      "x shape: (5,)\n",
      "x size:  5\n",
      "x dtype:  int32\n"
     ]
    }
   ],
   "source": [
    "x=np.array([1,2,3,4,5])\n",
    "# 秩\n",
    "print (\"x ndim: \", x.ndim)\n",
    "# 维度\n",
    "print (\"x shape:\", x.shape)\n",
    "# 数组元素的总个数\n",
    "print (\"x size: \", x.size)\n",
    "# ndarray 对象的元素类型\n",
    "print (\"x dtype: \", x.dtype)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x:  [1.3 2.2 1.7]\n",
      "x ndim:  1\n",
      "x shape: (3,)\n",
      "x size:  3\n",
      "x dtype:  float64\n"
     ]
    }
   ],
   "source": [
    "# 1-D \n",
    "x = np.array([1.3 , 2.2 , 1.7])\n",
    "print (\"x: \", x)\n",
    "print (\"x ndim: \", x.ndim)\n",
    "print (\"x shape:\", x.shape)\n",
    "print (\"x size: \", x.size)\n",
    "print (\"x dtype: \", x.dtype) # 注意 float datatype"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x:\n",
      " [[[1 2 3]\n",
      "  [4 5 6]\n",
      "  [7 8 9]]]\n",
      "x ndim:  3\n",
      "x shape: (1, 3, 3)\n",
      "x size:  9\n",
      "x dtype:  int32\n"
     ]
    }
   ],
   "source": [
    "# 3-D  (矩阵)\n",
    "x = np.array([[[1,2,3], [4,5,6], [7,8,9]]])\n",
    "print (\"x:\\n\", x)\n",
    "print (\"x ndim: \", x.ndim)\n",
    "print (\"x shape:\", x.shape)\n",
    "print (\"x size: \", x.size)\n",
    "print (\"x dtype: \", x.dtype)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([1, 2]), [1, 2])"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#array转化为list\n",
    "a = np.array([1,2])\n",
    "b = a.tolist()\n",
    "a,b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([2, 1, 2, 6, 4]), array([[2, 1, 2, 6, 4]]))"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#增加一个维度 []→[[]]\n",
    "x = np.random.randint(1, 8, size=5)\n",
    "x1 = x[np.newaxis, :]\n",
    "x,x1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 基本的切片与索引"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "ndarray对象的内容可以通过索引或切片来访问和修改。\n",
    "与 Python 中 list 的切片操作一样，ndarray 数组可以基于 0 - n 的下标进行索引，切片对象可以通过内置的 slice 函数从原数组中切割出一个新数组。\n",
    "slice(start,stop , step )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x[0]:  1\n",
      "x:  [0 2 3]\n"
     ]
    }
   ],
   "source": [
    "# 索引\n",
    "x = np.array([1, 2, 3])\n",
    "print (\"x[0]: \", x[0])\n",
    "x[0] = 0\n",
    "print (\"x: \", x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0 1 2 3 4 5 6 7 8 9]\n",
      "[2 4 6]\n"
     ]
    }
   ],
   "source": [
    "# slice函数切片\n",
    "a = np.arange(10)\n",
    "print(a)\n",
    "s = slice(2,7,2)   # 从索引2开始到索引7停止 ， 间隔为2\n",
    "print (a[s])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 1  2  3  4]\n",
      " [ 5  6  7  8]\n",
      " [ 9 10 11 12]]\n",
      "x column 1:  [ 2  6 10]\n",
      "x row 0:  [1 2 3 4]\n",
      "x rows 0,1,2 & cols 1,2: \n",
      " [[ 2  3]\n",
      " [ 6  7]\n",
      " [10 11]]\n"
     ]
    }
   ],
   "source": [
    "# 切片\n",
    "#冒号 :的解释\n",
    "#如果只放置一个参数，如 [1]，将返回与该索引相对应的单个元素。\n",
    "#如果为 [1:]，表示从该索引[1]开始以后的所有项都将被提取。\n",
    "#如果使用了两个参数，如 [1:3]，那么则提取两个索引(不包括停止索引)之间的项，即[1][2]\n",
    "x = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])\n",
    "print (x)\n",
    "print (\"x column 1: \", x[:, 1]) \n",
    "print (\"x row 0: \", x[0, :]) \n",
    "print (\"x rows 0,1,2 & cols 1,2: \\n\", x[:3, 1:3])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 高级索引"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "NumPy 比一般的 Python 序列提供更多的索引方式。除了用整数和切片的索引外，数组可以由整数数组索引、布尔索引等。\n",
    "\n",
    "布尔索引通过布尔运算（如：比较运算符）来获取符合指定条件的元素的数组。\n",
    "\n",
    "花式索引根据索引数组的值作为目标数组的某个轴的下标来取值。对于使用一维整型数组作为索引，如果目标是一维数组，那么索引的结果就是对应位置的元素；如果目标是二维数组，那么就是对应下标的行。花式索引跟切片不一样，它总是将数据复制到新数组中。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 整数索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 1  2  3  4]\n",
      " [ 5  6  7  8]\n",
      " [ 9 10 11 12]]\n",
      "rows_to_get:  [0 1 2]\n",
      "cols_to_get:  [0 2 1]\n",
      "indexed values:  [ 1  7 10]\n"
     ]
    }
   ],
   "source": [
    "print (x)\n",
    "rows_to_get = np.arange(len(x))\n",
    "print (\"rows_to_get: \", rows_to_get)\n",
    "cols_to_get = np.array([0, 2, 1])\n",
    "print (\"cols_to_get: \", cols_to_get)\n",
    "print (\"indexed values: \", x[rows_to_get, cols_to_get])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 布尔索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x:\n",
      " [[1 2]\n",
      " [3 4]\n",
      " [5 6]]\n",
      "x > 2:\n",
      " [[False False]\n",
      " [ True  True]\n",
      " [ True  True]]\n",
      "x[x > 2]:\n",
      " [3 4 5 6]\n"
     ]
    }
   ],
   "source": [
    "# 布尔值索引\n",
    "x = np.array([[1,2], [3, 4], [5, 6]])\n",
    "print (\"x:\\n\", x)\n",
    "print (\"x > 2:\\n\", x > 2)\n",
    "print (\"x[x > 2]:\\n\", x[x > 2])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 花式索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x:\n",
      " [[ 0  1  2  3]\n",
      " [ 4  5  6  7]\n",
      " [ 8  9 10 11]\n",
      " [12 13 14 15]\n",
      " [16 17 18 19]\n",
      " [20 21 22 23]\n",
      " [24 25 26 27]\n",
      " [28 29 30 31]]\n",
      "传入顺序索引数组:\n",
      " [[16 17 18 19]\n",
      " [ 8  9 10 11]\n",
      " [ 4  5  6  7]\n",
      " [28 29 30 31]]\n",
      "传入倒序索引数组:\n",
      " [[16 17 18 19]\n",
      " [24 25 26 27]\n",
      " [28 29 30 31]\n",
      " [ 4  5  6  7]]\n",
      "传入多个索引数组:\n",
      " [[ 4  7  5  6]\n",
      " [20 23 21 22]\n",
      " [28 31 29 30]\n",
      " [ 8 11  9 10]]\n"
     ]
    }
   ],
   "source": [
    "# 花式索引\n",
    "x=np.arange(32).reshape((8,4))\n",
    "print(\"x:\\n\",x)\n",
    "print (\"传入顺序索引数组:\\n\",x[[4,2,1,7]])\n",
    "print (\"传入倒序索引数组:\\n\",x[[-4,-2,-1,-7]])\n",
    "print (\"传入多个索引数组:\\n\",x[np.ix_([1,5,7,2],[0,3,1,2])])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 按照条件返回索引"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "numpy.argmax() 和 numpy.argmin()函数分别沿给定轴返回最大和最小元素的索引。\n",
    "numpy.nonzero() 函数返回输入数组中非零元素的索引。\n",
    "numpy.where() 函数返回输入数组中满足给定条件的元素的索引。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "数组展开最大元素的索引： 7\n",
      "数组按列最大元素的索引： [1 2 0]\n",
      "数组按行最大元素的索引： [2 0 1]\n",
      "数组展开最大元素的索引： 5\n",
      "数组按列最大元素的索引： [0 1 1]\n",
      "数组按行最大元素的索引： [0 2 0]\n",
      "数组中非零元素的索引： (array([0, 0, 0, 1, 1, 1, 2, 2, 2], dtype=int64), array([0, 1, 2, 0, 1, 2, 0, 1, 2], dtype=int64))\n",
      "数组中大于50的索引： (array([0, 1, 2, 2], dtype=int64), array([2, 0, 1, 2], dtype=int64))\n",
      "使用这些索引来获取满足条件的元素： [70 80 90 60]\n"
     ]
    }
   ],
   "source": [
    "a = np.array([[30,40,70],[80,20,10],[50,90,60]])\n",
    "print (\"数组展开最大元素的索引：\",np.argmax(a)) \n",
    "print (\"数组按列最大元素的索引：\",np.argmax(a, axis =  0)) \n",
    "print (\"数组按行最大元素的索引：\",np.argmax(a, axis =  1)) \n",
    "print (\"数组展开最大元素的索引：\",np.argmin(a)) \n",
    "print (\"数组按列最大元素的索引：\",np.argmin(a, axis =  0)) \n",
    "print (\"数组按行最大元素的索引：\",np.argmin(a, axis =  1))\n",
    "print (\"数组中非零元素的索引：\",np.nonzero (a))\n",
    "print (\"数组中大于50的索引：\",np.where(a > 50))\n",
    "print ('使用这些索引来获取满足条件的元素：',a[np.where(a > 50)])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 二、通用函数：快速的元素级数组函数\n",
    "通用函数（即ufunc）是一种对ndarray中的数据执行元素级运算的函数。你可以将其看做简单函数（接受一个或多个标量值，并产生一个或多个标量值）的矢量化包装器。本部分主要介绍一元、二元通用函数以及执行特定矢量化运算的特殊方法。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 一元通用函数"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "abs、fabs               计算整数、浮点数或复数的绝对值。对于非复数值，可以使用更快的fabs\n",
    "sqrt                  计算各元素的平方根。相当于arr**0.5\n",
    "square                  计算各元素的平方。相当于arr**2\n",
    "exp                  计算各元素的指数e \n",
    "log、log10、log2、loglp      分别为自然对数（底数为e）、底数为10的1og、底数为2的log、log（1+x）\n",
    "sign                  计算各元素的正负号：1（正数）、0（零）、-1（负数）\n",
    "ceil                  计算各元素的ceiling值，即大于等于该值的最小整数\n",
    "floor                  计算各元素的floor值，即小于等于该值的最大整数\n",
    "rint                  将各元素值四舍五入到最接近的整数，保留dtype \n",
    "modf                  将数组的小数和整数部分以两个独立数组的形式返回\n",
    "isnan                  返回一个表示“哪些值是NaN（这不是一个数字）”的布尔型数组\n",
    "isfinite、isinf            分别返回一个表示“哪些元素是有穷的（非inf，非NaN）”或“哪些元素是无穷的”的布尔型数组\n",
    "cos、cosh、sin、sinh、tan、tanh 普通型和双曲型三角函数\n",
    "arccos、arccosh、arcsin、      反三角函数\n",
    "arcsinh、arctan、arctanh logical_not 计算各元素notx的真值。相当于-arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "原数组： [  1.      5.55  123.     -0.567  25.532]\n",
      "绝对值： [  1.      5.55  123.      0.567  25.532]\n",
      "平方根： [ 1.          2.3558438  11.09053651         nan  5.05291995]\n",
      "平方： [1.00000000e+00 3.08025000e+01 1.51290000e+04 3.21489000e-01\n",
      " 6.51883024e+02]\n",
      "保留一位小数： [  1.    5.6 123.   -0.6  25.5]\n",
      "向下取整： [  1.   5. 123.  -1.  25.]\n",
      "向上取整： [  1.   6. 123.  -0.  26.]\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py:4: RuntimeWarning: invalid value encountered in sqrt\n",
      "  after removing the cwd from sys.path.\n"
     ]
    }
   ],
   "source": [
    "a = np.array([1.0,5.55,123,-0.567,25.532])  \n",
    "print  ('原数组：',a)\n",
    "print('绝对值：',np.abs(a))\n",
    "print('平方根：',np.sqrt(a))\n",
    "print('平方：',np.square(a))\n",
    "print ('保留一位小数：',np.around(a, decimals =  1))\n",
    "print ('向下取整：',np.floor(a))\n",
    "print ('向上取整：',np.ceil(a))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x     = [1, 2, 3]\n",
      "e^x   = [ 2.71828183  7.3890561  20.08553692]\n",
      "2^x   = [2. 4. 8.]\n",
      "3^x   = [ 3  9 27]\n",
      "ln(x)    = [0.         0.69314718 1.09861229]\n",
      "log2(x)  = [0.        1.        1.5849625]\n",
      "log10(x) = [0.         0.30103    0.47712125]\n"
     ]
    }
   ],
   "source": [
    "#指数运算\n",
    "x = [1, 2, 3]\n",
    "print(\"x     =\", x)\n",
    "print(\"e^x   =\", np.exp(x))\n",
    "print(\"2^x   =\", np.exp2(x))\n",
    "print(\"3^x   =\", np.power(3, x))\n",
    "print(\"ln(x)    =\", np.log(x))\n",
    "print(\"log2(x)  =\", np.log2(x))\n",
    "print(\"log10(x) =\", np.log10(x))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "theta      =  [0.         1.57079633 3.14159265]\n",
      "sin(theta) =  [0.0000000e+00 1.0000000e+00 1.2246468e-16]\n",
      "cos(theta) =  [ 1.000000e+00  6.123234e-17 -1.000000e+00]\n",
      "tan(theta) =  [ 0.00000000e+00  1.63312394e+16 -1.22464680e-16]\n"
     ]
    }
   ],
   "source": [
    "theta = np.linspace(0, np.pi, 3)\n",
    "print(\"theta      = \", theta)\n",
    "print(\"sin(theta) = \", np.sin(theta))\n",
    "print(\"cos(theta) = \", np.cos(theta))\n",
    "print(\"tan(theta) = \", np.tan(theta))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x         =  [-1, 0, 1]\n",
      "arcsin(x) =  [-1.57079633  0.          1.57079633]\n",
      "arccos(x) =  [3.14159265 1.57079633 0.        ]\n",
      "arctan(x) =  [-0.78539816  0.          0.78539816]\n"
     ]
    }
   ],
   "source": [
    "x = [-1, 0, 1]\n",
    "print(\"x         = \", x)\n",
    "print(\"arcsin(x) = \", np.arcsin(x))\n",
    "print(\"arccos(x) = \", np.arccos(x))\n",
    "print(\"arctan(x) = \", np.arctan(x))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 二元通用函数"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "+\tnp.add\t       加法(例如，1 + 1 = 2)\n",
    "-\tnp.subtract\t     减法(例如，3 - 2 = 1)\n",
    "-\tnp.negative\t     一元否定(例如，-2)\n",
    "*\tnp.multiply\t      乘法(例如，2 * 3 = 6)\n",
    "/\tnp.divide\t      除法(例如，3 / 2 = 1.5)\n",
    "//\tnp.floor_divide\t   取整除法(例如，3 // 2 = 1)\n",
    "**\tnp.power\t     指数(例如，2 ** 3 = 8)\n",
    "%\tnp.mod\t       模数/余数(例如，9 % 4 = 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x     = [0 1 2 3]\n",
      "       算术操作结果            对应Ufunc函数结果\n",
      "x + 5 = [5 6 7 8]                  [5 6 7 8]\n",
      "x - 5 = [-5 -4 -3 -2]              [-5 -4 -3 -2]\n",
      "x * 2 = [0 2 4 6]                  [0 2 4 6]\n",
      "x / 2 = [0.  0.5 1.  1.5]          [0.  0.5 1.  1.5]\n",
      "x // 2 = [0 0 1 1]                 [0 0 1 1]\n",
      "-x     =  [ 0 -1 -2 -3]            [ 0 -1 -2 -3]\n",
      "x ** 2 =  [0 1 4 9]                [0 1 4 9]\n",
      "x % 2  =  [0 1 0 1]                [0 1 0 1]\n"
     ]
    }
   ],
   "source": [
    "x = np.arange(4)\n",
    "print(\"x     =\", x)\n",
    "print(\"       算术操作结果            对应Ufunc函数结果\")\n",
    "print(\"x + 5 =\", x + 5,\"                \",np.add(x,5))\n",
    "print(\"x - 5 =\", x - 5,\"            \",np.subtract(x,5))\n",
    "print(\"x * 2 =\", x * 2,\"                \",np.multiply(x,2))\n",
    "print(\"x / 2 =\", x / 2,\"        \",np.divide(x,2))\n",
    "print(\"x // 2 =\", x // 2,\"               \",np.floor_divide(x,2))\n",
    "print(\"-x     = \", -x,\"          \",np.negative(x))\n",
    "print(\"x ** 2 = \", x ** 2,\"              \",np.power(x,2))\n",
    "print(\"x % 2  = \", x % 2,\"              \",np.mod(x,2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 执行特定矢量化运算的特殊ufunc方法"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "NumPy的各个二元ufunc都有一些用于执行特定矢量化运算的特殊方法。\n",
    "reduce（x）reduce接受一个数组参数，并通过一系列的二元运算对其值进行聚合（可指明轴向）\n",
    "accumulate（x）聚合值，保留所有局部聚合结果\n",
    "outer（x，y）对x和y中的每对元素应用原始运算。结果数组的形状为x.shape+y.shape\n",
    "reduceat（x，bins）“局部”约简（也就是groupby）。约简数据的各个切片以产生聚合型数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(45, 45)"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#我们可以用np.add.reduce对数组中各个元素进行求和。\n",
    "#起始值取决于ufunc（对于add的情况，就是0）。如果设置了轴号，约简运算就会沿该轴向执行。\n",
    "arr=np. arange(10)\n",
    "np.add.reduce(arr),arr.sum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[ True,  True,  True,  True],\n",
       "        [False,  True,  True, False],\n",
       "        [ True,  True,  True,  True],\n",
       "        [ True, False,  True, False],\n",
       "        [ True,  True,  True,  True]]),\n",
       " array([ True, False,  True, False,  True]))"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#用np.1ogical_and检查数组各行中的值是否是有序的：\n",
    "arr=np.random.randn(5,5)\n",
    "arr[::2].sort(1)#对部分行进行排序\n",
    "arr[:,:-1]<arr[:,1:],np.logical_and.reduce(arr[:,:-1]<arr[:,1:],axis=1)#1ogical_and.reduce跟a11方法是等价的。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  1,  3,  6, 10],\n",
       "       [ 5, 11, 18, 26, 35],\n",
       "       [10, 21, 33, 46, 60]], dtype=int32)"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#accumulate跟reduce的关系就像cumsum跟sum的关系那样。它产生一个跟原数组大小相同的中间“累计”值数组：\n",
    "arr=np. arange(15). reshape((3,5))\n",
    "np.add.accumulate(arr, axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([0, 1, 1, 2, 2]), array([[0, 0, 0, 0, 0],\n",
       "        [0, 1, 2, 3, 4],\n",
       "        [0, 1, 2, 3, 4],\n",
       "        [0, 2, 4, 6, 8],\n",
       "        [0, 2, 4, 6, 8]]))"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#outer 计算两个数组的叉积\n",
    "arr=np.arange(3).repeat([1,2,2])\n",
    "arr,np.multiply.outer(arr, np. arange(5))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3, 4, 5)"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#outer输出结果的维度是两个输入数据的维度之和：\n",
    "result = np.subtract.outer(np.random.randn(3, 4), np.random.randn(5))\n",
    "result.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([10, 18, 17], dtype=int32)"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#reduceat用于对数据各切片进行聚合的groupby运算。\n",
    "arr = np.arange(10)\n",
    "np.add.reduceat(arr, [0, 5, 8])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 三、统计方法"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "NumPy 提供了很多统计函数，用于从数组中查找最小元素，最大元素，百分位标准差和方差等。\n",
    "numpy.min()          求最小值\n",
    "numpy.amin()       用于计算数组中的元素沿指定轴的最小值。\n",
    "numpy.max()          求最大值\n",
    "numpy.amax()       用于计算数组中的元素沿指定轴的最大值。\n",
    "numpy.ptp()        函数计算数组中元素最大值与最小值的差（最大值 - 最小值）。\n",
    "numpy.percentile(a, q, axis)百分位数是统计中使用的度量，表示小于这个值的观察值的百分比。 \n",
    "numpy.sum()          计算元素和\n",
    "numpy.prod()         计算元素乘积\n",
    "numpy.std()          计算标准差\n",
    "numpy.var()          计算方差\n",
    "numpy.any()          评估任何元素是否为真\n",
    "numpy.all()\t        评估所有元素是否为真\n",
    "numpy.median()      函数用于计算数组 a 中元素的中位数（中值）\n",
    "numpy.mean()        函数返回数组中元素的算术平均值。\n",
    "numpy.average()      函数根据在另一个数组中给出的各自的权重计算数组中元素的加权平均值。\n",
    "numpy.cumsum()      所有元素的累计和\n",
    "numpy.cumprod()     所有元素的累计积"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[3 7 5]\n",
      " [8 4 3]\n",
      " [2 4 9]]\n",
      "数组中的最小值： 2 2\n",
      "每行的最小值： [3 3 2]\n",
      "每列的最小值： [2 4 3]\n",
      "数组中的最大值： 9 9\n",
      "每行的最大值： [7 8 9]\n",
      "每列的最大值： [8 7 9]\n",
      "每行最大值与最小值的差： [4 5 7]\n",
      "在横行上求50% 的分位数： [5. 4. 4.]\n",
      "在横行上求中位数（中值）： [5. 4. 4.]\n",
      "在横行上求算术平均值： [5. 5. 5.]\n",
      "所有元素的累计和： [ 3 10 15 23 27 30 32 36 45]\n",
      "所有元素的累计积： [     3     21    105    840   3360  10080  20160  80640 725760]\n"
     ]
    }
   ],
   "source": [
    "a = np.array([[3,7,5],[8,4,3],[2,4,9]])\n",
    "print(a)\n",
    "print (\"数组中的最小值：\",np.amin(a),np.min(a))\n",
    "print (\"每行的最小值：\",np.amin(a,1))\n",
    "print (\"每列的最小值：\",np.amin(a,0))\n",
    "print (\"数组中的最大值：\",np.amax(a),np.max(a))\n",
    "print (\"每行的最大值：\",np.amax(a, axis =  1))\n",
    "print (\"每列的最大值：\",np.amax(a, axis =  0))\n",
    "print (\"每行最大值与最小值的差：\",np.ptp(a,axis =  1))\n",
    "print (\"在横行上求50% 的分位数：\",np.percentile(a, 50,axis =  1)) \n",
    "print (\"在横行上求中位数（中值）：\",np.median(a, axis =  1))\n",
    "print (\"在横行上求算术平均值：\",np.mean(a, axis =  1))\n",
    "print (\"所有元素的累计和：\",np.cumsum(a))\n",
    "print (\"所有元素的累计积：\",np.cumprod(a))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "调用 average() 函数：\n",
      "2.5\n",
      "加上权重后再次调用 average() 函数：\n",
      "2.0\n",
      "权重的和：\n",
      "(2.0, 10.0)\n"
     ]
    }
   ],
   "source": [
    "a = np.array([1,2,3,4])  \n",
    "print ('调用 average() 函数：')\n",
    "print (np.average(a))\n",
    "# 不指定权重时相当于 mean 函数\n",
    "print ('加上权重后再次调用 average() 函数：')\n",
    "print (np.average(a,weights = [4,3,2,1]))\n",
    "# 如果 returned 参数设为 true，则返回权重的和  \n",
    "print ('权重的和：')\n",
    "print (np.average([1,2,3,  4],weights =  [4,3,2,1], returned =  True))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 四、排序\n",
    "跟Python内置的列表类型一样，NumPy数组也可以通过sort方法就地排序"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "排序前：\n",
      " [-1.09423727  0.16327629 -0.39470357 -0.27369042 -1.20361238 -0.4834135\n",
      " -0.93118398  0.14813413]\n",
      "排序后：\n",
      " [-1.20361238 -1.09423727 -0.93118398 -0.4834135  -0.39470357 -0.27369042\n",
      "  0.14813413  0.16327629]\n"
     ]
    }
   ],
   "source": [
    "arr=np.random.randn(8)\n",
    "print('排序前：\\n',arr)\n",
    "arr.sort()\n",
    "print('排序后：\\n',arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "排序前：\n",
      " [[-0.15975062 -0.32468362 -0.1220071 ]\n",
      " [-0.71144555  1.22757902  0.86319888]\n",
      " [ 0.25438513 -0.30601358  1.29707533]\n",
      " [-0.71755231 -0.29995742  0.5938006 ]\n",
      " [-0.56019644  1.04587863  0.19253527]]\n",
      "排序后：\n",
      " [[-0.32468362 -0.15975062 -0.1220071 ]\n",
      " [-0.71144555  0.86319888  1.22757902]\n",
      " [-0.30601358  0.25438513  1.29707533]\n",
      " [-0.71755231 -0.29995742  0.5938006 ]\n",
      " [-0.56019644  0.19253527  1.04587863]]\n"
     ]
    }
   ],
   "source": [
    "#多维数组可以在任何一个轴向上进行排序，只需将轴编号传给sort即可\n",
    "arr=np.random.randn(5,3)\n",
    "print('排序前：\\n',arr)\n",
    "arr.sort(1)\n",
    "print('排序后：\\n',arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-1.7198952770284313"
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#np.sort返回的是数组的已排序副本，而就地排序则会修改数组本身。计算数1分位数最简单的办法是对其进行排序，然后选取特定位置的值：\n",
    "large_arr=np.random.randn(1000)\n",
    "large_arr.sort()\n",
    "large_arr[int(0.05*len(large_arr))]#5%分位数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 五、数据的唯一化和集合运算"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "NumPy提供了一些针对一维ndarray的基本集合运算。最常用的可能要数np.unique了，它用于找出数组中的唯一值并返回已排序的结果。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a中的唯一元素: [3 5 7]\n"
     ]
    }
   ],
   "source": [
    "a = np.array([1,2,3,4,5,6])\n",
    "b = np.array([[3,7,5,5,5,3]])\n",
    "print(\"a中的唯一元素:\",np.unique(b))"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "集合运算函数\n",
    "intersect1d（x，y）计算x和y中的公共元素，并返回有序结果\n",
    "union1d（x，y）计算x和y的并集，并返回有序结果\n",
    "in1d（x，y）得到一个表示“x的元素是否包含于y”的布尔型数组\n",
    "setdiff1d（x，y）集合的差，即元素在x中且不在y中\n",
    "setxor1d（x，y）集合的对称差，即存在于一个数组中但不同时存在于两个数组中的元素"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a和b中的公共元素： [3 5]\n",
      "a的元素是否包含于b [False False  True False  True False]\n"
     ]
    }
   ],
   "source": [
    "print(\"a和b中的公共元素：\",np.intersect1d(a,b))\n",
    "print(\"a的元素是否包含于b\",np.in1d(a,b))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 六、随机数生成\n",
    "numpy.random模块对Python内置的random进行了补充，增加了一些用于高效生成多种概率分布的样本值的函数。"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "部分numpy.random函数\n",
    "\n",
    "numpy.seed() 随机数生成种子\n",
    "numpy.permutation() 返回一个序列的随机排列或返回一个随机排列的范围\n",
    "numpy.shuffle() 对一个序列就地随机排列\n",
    "numpy.rand() 产生均匀分布的样本值\n",
    "numpy.randint() 从给定的上下限范围内随机选取整数\n",
    "numpy.randn() 产生生态分布，平均值为0，标准差为1的样本值\n",
    "numpy.binomial() 产生二项分布的样本值\n",
    "numpy.normal() 产生正态分布样本值\n",
    "numpy.beta 产生beta分布的样本值\n",
    "numpy.chisqure() 产生卡方分布的样本值\n",
    "numpy.gamma() 产生gamma分布的样本值\n",
    "numpy.uniform() 产生[0,1)均匀分布的样本值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "正态分布 (loc均值，scale标准差，size数量):\n",
      " [ 0.46384438 -2.31677463  0.84148649  1.39812905 -0.2515894   0.61764442\n",
      "  0.44076124 -1.07475377 -2.83993261  0.55597439 -0.38872308 -0.70239379\n",
      " -0.5789592  -2.41054828  0.92540134  1.42467094]\n",
      "正态分布4*4:\n",
      " [[-0.07244142 -1.0878258   0.31374739  0.24233281]\n",
      " [ 0.35617531  0.7546339   1.14400791 -0.51559365]\n",
      " [ 1.41558495 -1.1836136  -0.70112879  1.00018804]\n",
      " [-0.36122484 -0.1997344  -1.31597231 -0.93843363]]\n"
     ]
    }
   ],
   "source": [
    "print(\"正态分布 (loc均值，scale标准差，size数量):\\n\",np.random.normal(loc = 0,scale=1,size =16))\n",
    "print(\"正态分布4*4:\\n\",np.random.normal(size = (4,4)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 七、NumPy 矩阵库(Matrix)及其计算\n",
    "本部分主要介绍矩阵及其相关的线性代数的计算"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "NumPy 中包含了一个矩阵库numpy.matlib，该模块中的函数返回的是一个矩阵，而不是 ndarray 对象。\n",
    "一个m*n的矩阵是一个由行m（row）列n（column）元素排列成的矩形阵列。\n",
    "矩阵里的元素可以是数字、符号或数学式。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 创建矩阵"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "numpy.matlib.empty(shape, dtype, order)函数返回一个新的矩阵\n",
    "numpy.matlib.zeros((2,3))创建一个以 0 填充的矩阵\n",
    "numpy.matlib.ones((2,3))创建一个以 1 填充的矩阵\n",
    "numpy.matlib.eye(n, M,k, dtype)返回一个矩阵，对角线元素为 1，其他位置为零\n",
    "numpy.matlib.identity()返回给定大小的单位矩阵\n",
    "numpy.matlib.rand() 函数创建一个给定大小的矩阵，数据是随机填充的。\n",
    "参数说明：\n",
    "shape: 定义新矩阵形状的整数或整数元组\n",
    "Dtype: 可选，数据类型\n",
    "order: C（行序优先） 或者 F（列序优先）\n",
    "n: 返回矩阵的行数\n",
    "M: 返回矩阵的列数，默认为 n\n",
    "k: 对角线的索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2*3矩阵：\n",
      " [[4.24399158e-314 8.48798317e-314 1.27319747e-313]\n",
      " [1.69759663e-313 2.12199579e-313 2.54639495e-313]]\n",
      "2*3矩阵：\n",
      " [[0. 0. 0.]\n",
      " [0. 0. 0.]]\n",
      "2*3矩阵：\n",
      " [[1. 1. 1.]\n",
      " [1. 1. 1.]]\n",
      "3*4矩阵：\n",
      " [[1. 0. 0. 0.]\n",
      " [0. 1. 0. 0.]\n",
      " [0. 0. 1. 0.]]\n",
      "大小为 5，类型位浮点型的矩阵：\n",
      " [[1. 0. 0. 0. 0.]\n",
      " [0. 1. 0. 0. 0.]\n",
      " [0. 0. 1. 0. 0.]\n",
      " [0. 0. 0. 1. 0.]\n",
      " [0. 0. 0. 0. 1.]]\n",
      "3*3随机填充数据矩阵：\n",
      " [[0.68154925 0.8388852  0.2949826 ]\n",
      " [0.96304809 0.27917241 0.08094938]\n",
      " [0.65357831 0.2416451  0.93637365]]\n"
     ]
    }
   ],
   "source": [
    "print(\"2*3矩阵：\\n\",np.matlib.empty((2,3)))\n",
    "print(\"2*3矩阵：\\n\",np.matlib.zeros((2,3)))\n",
    "print(\"2*3矩阵：\\n\",np.matlib.ones((2,3)))\n",
    "print(\"3*4矩阵：\\n\",np.matlib.eye(n =  3, M =  4, k =  0, dtype =  float))\n",
    "print(\"大小为 5，类型位浮点型的矩阵：\\n\",np.matlib.identity(5, dtype =  float))\n",
    "print(\"3*3随机填充数据矩阵：\\n\",np.matlib.rand(3,3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[1, 2],\n",
       "        [3, 4]])"
      ]
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#矩阵总是二维的，而 ndarray 是一个 n 维数组。 两个对象都是可互换的。\n",
    "i = np.matrix('1,2;3,4')  \n",
    "i"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2],\n",
       "       [3, 4]])"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "j = np.asarray(i)  \n",
    "j"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 矩阵运算\n",
    "线性代数（如矩阵乘法、矩阵分解、行列式以及其他方阵数学等）是任何数组库的重要组成部分。"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "NumPy 提供了线性代数函数库 linalg，该库包含了线性代数所需的所有功能\n",
    "diag()   以一维数组的形式返回方阵的对角线（或非对角线）元素，或将一维数组转换为方阵（非对角线元素为0）\n",
    "dot()    两个数组的点积，即元素对应相乘。\n",
    "inner()   两个数组的内积\n",
    "matmul()  两个数组的矩阵积\n",
    "det()    计算输入矩阵的行列式。\n",
    "inv()   计算矩阵的乘法逆矩阵\n",
    "trace()  计算对角线元素的和\n",
    "eig()   计算方阵的本征值和本征向量\n",
    "pinv()  计算矩阵的Moore-Penrose伪逆qr计算QR分解\n",
    "solve()   求解线性矩阵方程Ax=b，其中A为一个方阵\n",
    "svd()   计算奇异值分解（SVD）\n",
    "lstsq()  计算Ax=b的最小二乘解"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a:\n",
      " [[1 2]\n",
      " [3 4]]\n",
      "b:\n",
      " [[11 12]\n",
      " [13 14]]\n",
      "点积:\n",
      " [[37 40]\n",
      " [85 92]]\n",
      "内积:\n",
      " [[35 41]\n",
      " [81 95]]\n",
      "矩阵积:\n",
      " [[37 40]\n",
      " [85 92]]\n",
      "行列式:\n",
      " -2.0000000000000004\n",
      "a 的逆：\n",
      " [[-2.   1. ]\n",
      " [ 1.5 -0.5]]\n"
     ]
    },
    {
     "ename": "AttributeError",
     "evalue": "module 'numpy.linalg' has no attribute 'trace'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-74-a223fabc1ced>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      8\u001b[0m \u001b[0mprint\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;34m\"行列式:\\n\"\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlinalg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdet\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      9\u001b[0m \u001b[0mprint\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;34m'a 的逆：\\n'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlinalg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0minv\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 10\u001b[1;33m \u001b[0mprint\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;34m'a 的对角线和：\\n'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlinalg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtrace\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     11\u001b[0m \u001b[0mprint\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;34m'a 的本征值和本征向量：\\n'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlinalg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0meig\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     12\u001b[0m \u001b[0mprint\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;34m'a 的伪逆矩阵：\\n'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlinalg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpinv\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ma\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mAttributeError\u001b[0m: module 'numpy.linalg' has no attribute 'trace'"
     ]
    }
   ],
   "source": [
    "a = np.array([[1,2],[3,4]])\n",
    "b = np.array([[11,12],[13,14]])\n",
    "print(\"a:\\n\",a)\n",
    "print(\"b:\\n\",b)\n",
    "print (\"点积:\\n\",np.dot(a,b))\n",
    "print (\"内积:\\n\",np.inner(a,b))\n",
    "print (\"矩阵积:\\n\",np.matmul(a,b))\n",
    "print (\"行列式:\\n\",np.linalg.det(a))\n",
    "print ('a 的逆：\\n',np.linalg.inv(a) )\n",
    "print ('a 的对角线和：\\n',np.linalg.trace(a))\n",
    "print ('a 的本征值和本征向量：\\n',np.linalg.eig(a))\n",
    "print ('a 的伪逆矩阵：\\n',np.linalg.pinv(a))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "计算：A^(-1)B：\n",
      "[[ 5.]\n",
      " [ 3.]\n",
      " [-2.]]\n"
     ]
    }
   ],
   "source": [
    "#slove\n",
    "a = np.array([[1,1,1],[0,2,5],[2,5,-1]]) \n",
    "b = np.array([[6],[-4],[27]]) \n",
    "print ('计算：A^(-1)B：')\n",
    "x = np.linalg.solve(a,b) \n",
    "print (x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 6 24 16 22 17]\n",
      " [20 14 11 14 15]\n",
      " [ 5  9  3 14  9]\n",
      " [ 9  2 16  3 16]\n",
      " [24 21 20  7  8]]\n"
     ]
    }
   ],
   "source": [
    "#svd\n",
    "S = np.zeros([5,5])\n",
    "A=np.random.randint(1,25,[5,5])\n",
    "u,sigma,vt = np.linalg.svd(A)\n",
    "print(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py:9: FutureWarning: `rcond` parameter will change to the default of machine precision times ``max(M, N)`` where M and N are the input matrix dimensions.\n",
      "To use the future default and silence this warning we advise to pass `rcond=None`, to keep using the old, explicitly pass `rcond=-1`.\n",
      "  if __name__ == '__main__':\n"
     ]
    }
   ],
   "source": [
    "#lstsq，传入A.T和观测值里的变量即可求得f(x)=a+bx里的a和b。a和b记录在lstsq函数的第一个返回值里\n",
    "#第一个返回值sol共有两个值，sol[0]即是估计出来的f(x)=a+bx里a，sol[1]代表f(x)=a+bx里b。因此f(x)为：y_fit = sol[0] + sol[1] * x\n",
    "m = 100\n",
    "x = np.linspace(-1, 1, m)\n",
    "y_exact = 1 + 2 * x\n",
    "xi = x + np.random.normal(0, 0.05, 100)\n",
    "yi = 1 + 2 * xi + np.random.normal(0, 0.05, 100)\n",
    "A = np.vstack([xi**0, xi**1])\n",
    "sol, r, rank, s = np.linalg.lstsq(A.T, yi)   #求取各个系数大小\n",
    "y_fit = sol[0] + sol[1] * x"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 八、高级数组操作\n",
    "除花式索引、切片、布尔条件取子集等操作之外，数组的操作方式还有很多。虽然pandas中的高级函数可以处理数据分析工作中的许多重型任务，但有时你还是需要编写一些在现有库中找不到的数据算法。本部分主要介绍转置数组、数组重塑、合并与拆分。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 翻转、转置数组"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "numpy.transpose(arr, axes)对换数组的维度，如形状 (2,3,4) transpose 后就变成 (4,3,2)。\n",
    "ndarray.T 和transpose() 相同"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[1, 3],\n",
       "        [2, 4]]), array([[1, 3],\n",
       "        [2, 4]]))"
      ]
     },
     "execution_count": 78,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# transpose,T\n",
    "a = np.array([[1,2],[3,4]])\n",
    "np.transpose(a),a.T"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 数组重塑\n",
    "鉴于我们已经学过的有关NumPy数组的知识，当你知道“无需复制任何数据，数组就能从一个形状转换为另一个形状”时应该会感到有一点吃惊。只需向数组的实例方法reshape传入一个表示新形状的元组即可实现该目的。假设有一个一维数组，我们希望将其重新排列为一个矩阵："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([0, 1, 2, 3, 4, 5, 6, 7]), array([[0, 1],\n",
       "        [2, 3],\n",
       "        [4, 5],\n",
       "        [6, 7]]))"
      ]
     },
     "execution_count": 79,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#numpy.reshape(arr, newshape, order='C') 不改变数据的条件下修改形状\n",
    "a = np.arange(8)\n",
    "b = a.reshape(4,2)\n",
    "a,b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[ 0,  1,  2],\n",
       "        [ 3,  4,  5],\n",
       "        [ 6,  7,  8],\n",
       "        [ 9, 10, 11],\n",
       "        [12, 13, 14]]),\n",
       " array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14]))"
      ]
     },
     "execution_count": 80,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#与reshape将一维数组转换为多维数组的运算过程相反的运算通常称为扁平化（flattening）或散开（raveling）：\n",
    "arr=np. arange(15). reshape((5,3))\n",
    "arr,arr.ravel()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])"
      ]
     },
     "execution_count": 82,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#如果没有必要，rave1不会产生源数据的副本（下面将详细介绍）。flatten方法的行为类似于rave1，只不过它总是返回数据的副本：\n",
    "arr.flatten()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 数组的合并和拆分"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "numpy.concatenate((a1, a2, ...), axis)沿指定轴axis连接相同形状的两个或多个数组\n",
    "numpy.stack(arrays, axis) 沿新轴axis连接数组序列\n",
    "                  便捷化函数：vstack、hstack、dstack以（沿轴0）（沿轴1）（沿轴2）的方式对数组进行堆叠\n",
    "numpy.split(ary, indices_or_sections, axis)将一个数组ary分割为indices_or_sections个子数组，axis是沿着哪个维度进行切向，默认为0，横向切分。为1时，纵向切分\n",
    "                  便捷化函数：hsplit、vsplit、dsplit split分别沿轴0、轴1、轴2进行拆分"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "第一个数组：\n",
      "[[1 2]\n",
      " [3 4]]\n",
      "第二个数组：\n",
      "[[5 6]\n",
      " [7 8]]\n",
      "沿轴 0 连接两个数组：\n",
      "[[1 2]\n",
      " [3 4]\n",
      " [5 6]\n",
      " [7 8]]\n",
      "沿轴 1 连接两个数组：\n",
      "[[1 2 5 6]\n",
      " [3 4 7 8]]\n"
     ]
    }
   ],
   "source": [
    "#concatenate\n",
    "a = np.array([[1,2],[3,4]])\n",
    "print ('第一个数组：')\n",
    "print (a)\n",
    "\n",
    "b = np.array([[5,6],[7,8]])\n",
    "print ('第二个数组：')\n",
    "print (b)\n",
    "\n",
    "# 两个数组的维度相同\n",
    "print ('沿轴 0 连接两个数组：')\n",
    "print (np.concatenate((a,b)))\n",
    "print ('沿轴 1 连接两个数组：')\n",
    "print (np.concatenate((a,b),axis = 1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "第一个数组：\n",
      "[[1 2]\n",
      " [3 4]]\n",
      "第二个数组：\n",
      "[[5 6]\n",
      " [7 8]]\n",
      "沿轴 0 堆叠两个数组：\n",
      "[[[1 2]\n",
      "  [3 4]]\n",
      "\n",
      " [[5 6]\n",
      "  [7 8]]]\n",
      "沿轴 1 堆叠两个数组：\n",
      "[[[1 2]\n",
      "  [5 6]]\n",
      "\n",
      " [[3 4]\n",
      "  [7 8]]]\n"
     ]
    }
   ],
   "source": [
    "#stack\n",
    "a = np.array([[1,2],[3,4]])\n",
    " \n",
    "print ('第一个数组：')\n",
    "print (a)\n",
    "\n",
    "b = np.array([[5,6],[7,8]])\n",
    "print ('第二个数组：')\n",
    "print (b)\n",
    "\n",
    "print ('沿轴 0 堆叠两个数组：')\n",
    "print (np.stack((a,b),0))\n",
    "print ('沿轴 1 堆叠两个数组：')\n",
    "print (np.stack((a,b),1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "第一个数组：\n",
      "[0 1 2 3 4 5 6 7 8]\n",
      "将数组分为三个大小相等的子数组：\n",
      "[array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8])]\n",
      "将数组在一维数组中表明的位置分割：\n",
      "[array([0, 1, 2, 3]), array([4, 5, 6]), array([7, 8])]\n"
     ]
    }
   ],
   "source": [
    "#split\n",
    "a = np.arange(9)\n",
    "print ('第一个数组：')\n",
    "print (a)\n",
    " \n",
    "print ('将数组分为三个大小相等的子数组：')\n",
    "b = np.split(a,3)\n",
    "print (b)\n",
    "\n",
    "print ('将数组在一维数组中表明的位置分割：')\n",
    "b = np.split(a,[4,7])\n",
    "print (b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 数组元素的添加与删除"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "numpy.append(arr, values, axis=None)在数组的末尾添加值。 追加操作会分配整个数组，并把原来的数组复制到新数组中。\n",
    "numpy.insert(arr, obj, values, axis)在给定索引obj之前，沿给定轴axis在输入数组arr中插入值values\n",
    "numpy.delete(arr, obj, axis)从输入数组arr中删除指定子数组的新数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "第一个数组：\n",
      "[[1 2 3]\n",
      " [4 5 6]]\n",
      "向数组添加元素：\n",
      "[1 2 3 4 5 6 7 8 9]\n"
     ]
    }
   ],
   "source": [
    "#append\n",
    "a = np.array([[1,2,3],[4,5,6]])\n",
    "print ('第一个数组：')\n",
    "print (a)\n",
    "print ('向数组添加元素：')\n",
    "print (np.append(a, [7,8,9]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2]\n",
      " [3 4]\n",
      " [5 6]]\n",
      "[ 1  2  3 11 12  4  5  6]\n",
      "[[ 1  2]\n",
      " [11 11]\n",
      " [ 3  4]\n",
      " [ 5  6]]\n"
     ]
    }
   ],
   "source": [
    "#insert\n",
    "a = np.array([[1,2],[3,4],[5,6]])\n",
    "print (a)\n",
    "print (np.insert(a,3,[11,12]))\n",
    "print (np.insert(a,1,[11],axis = 0))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0  1  2  3]\n",
      " [ 4  5  6  7]\n",
      " [ 8  9 10 11]]\n",
      "[ 0  1  3  4  5  6  7  8  9 10 11]\n",
      "[[ 0  1  3]\n",
      " [ 4  5  7]\n",
      " [ 8  9 11]]\n"
     ]
    }
   ],
   "source": [
    "#delete\n",
    "a = np.arange(12).reshape(3,4)\n",
    "print (a)\n",
    "print (np.delete(a,2))#删除展开后的第2列\n",
    "print (np.delete(a,2,axis = 1))#删除第二列"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 九、广播"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "广播(Broadcast)是 numpy 很重要的一个特性，它对不同形状(shape)的数组进行数值计算的方式， 通常在数组的算术运算对相应的元素进行。\n",
    "如果两个数组 a 和 b 形状相同，即满足 a.shape == b.shape，那么 a*b 的结果就是 a 与 b 数组对应位相乘。这要求维数相同，且各维度的长度相同。\n",
    "NumPy中的广播遵循一组严格的规则来确定两个数组之间的相互作用\n",
    "规则1：如果这两个数组的维数不同，则维数较少的数组的形状为衬垫在它的前面(左边)。\n",
    "规则2：如果两个数组的形状在任何维度中不匹配，则在该维度中形状等于1的数组将被拉伸以与另一个形状匹配。\n",
    "规则3：如果在任何维度中，大小不一致，且两者都不等于1，则会引发错误。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([5, 6, 7])"
      ]
     },
     "execution_count": 89,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#对于相同大小的数组，在逐个元素的基础上执行：\n",
    "a = np.array([0, 1, 2])\n",
    "b = np.array([5, 5, 5])\n",
    "a + b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([5, 6, 7])"
      ]
     },
     "execution_count": 90,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#广播允许在不同大小的数组上执行这些类型操作\n",
    "#例如，我们可以很容易地将标量(将其视为零维数组)添加到数组中：\n",
    "a + 5"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "5进入数组[5, 5, 5]，并加结果到a。\n",
    "我们也可以将其扩展到更高维度的数组。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 1., 1.],\n",
       "       [1., 1., 1.],\n",
       "       [1., 1., 1.]])"
      ]
     },
     "execution_count": 91,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 在将一维数组添加到二维数组时\n",
    "M = np.ones((3, 3))\n",
    "M"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 2., 3.],\n",
       "       [1., 2., 3.],\n",
       "       [1., 2., 3.]])"
      ]
     },
     "execution_count": 92,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "M + a"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "虽然这些例子相对容易理解，但更复杂的例子可能涉及两个数组的广播。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0 1 2]\n",
      "[[0]\n",
      " [1]\n",
      " [2]]\n"
     ]
    }
   ],
   "source": [
    "a = np.arange(3)\n",
    "b = np.arange(3)[:, np.newaxis]\n",
    "print(a)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1, 2],\n",
       "       [1, 2, 3],\n",
       "       [2, 3, 4]])"
      ]
     },
     "execution_count": 94,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a + b"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 广播实例与分析过程"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#向一维数组中添加一个二维数组\n",
    "M = np.ones((2, 3))\n",
    "a = np.arange(3)\n",
    "#两个数组都需要广播的例子\n",
    "c = np.arange(3).reshape((3, 1))\n",
    "d = np.arange(3)"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "思考：\n",
    "数组的形状如下\n",
    "M.shape = (2, 3)\n",
    "a.shape = (3,)\n",
    "c.shape = (3, 1)\n",
    "d.shape = (3,)\n",
    "\n",
    "我们通过规则1看到数组a,d维度较少，所以我们把1放在左边：\n",
    "M.shape -> (2, 3)\n",
    "a.shape -> (1, 3)\n",
    "c.shape -> (3, 1)\n",
    "d.shape -> (1, 3)\n",
    "\n",
    "根据规则2，我们现在看到第一个维度不一致，因此我们扩展这个维度来匹配：\n",
    "M.shape -> (2, 3)\n",
    "a.shape -> (2, 3)\n",
    "c.shape -> (3, 3)\n",
    "d.shape -> (3, 3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 2., 3.],\n",
       "       [1., 2., 3.]])"
      ]
     },
     "execution_count": 96,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#[[1. 1. 1.]    +    [0 1 2]\n",
    "# [1. 1. 1.]]\n",
    "M + a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1, 2],\n",
       "       [1, 2, 3],\n",
       "       [2, 3, 4]])"
      ]
     },
     "execution_count": 97,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#[[0]\n",
    "# [1]   +  [0 1 2]\n",
    "# [2]]         \n",
    "c+d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[1., 1.],\n",
       "        [1., 1.],\n",
       "        [1., 1.]]), array([0, 1, 2]))"
      ]
     },
     "execution_count": 98,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#形状不匹配的情况下又是如何呢？\n",
    "M = np.ones((3, 2))\n",
    "a = np.arange(3)\n",
    "M,a"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "同样，我们将从写出数组的形状开始：\n",
    "\n",
    "M.shape = (3, 2)\n",
    "a.shape = (3,)\n",
    "\n",
    "M.shape -> (3, 2)\n",
    "a.shape -> (1, 3)\n",
    "\n",
    "M.shape -> (3, 2)\n",
    "a.shape -> (3, 3)\n",
    "最终的形状不匹配，所以这两个数组是不兼容的，无法计算出结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "operands could not be broadcast together with shapes (3,2) (3,) ",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-99-e8522c44aa47>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      2\u001b[0m \u001b[1;31m#[1, 1],   +     [0, 1, 2]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      3\u001b[0m \u001b[1;31m#[1, 1]]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 4\u001b[1;33m \u001b[0mM\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0ma\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mValueError\u001b[0m: operands could not be broadcast together with shapes (3,2) (3,) "
     ]
    }
   ],
   "source": [
    "#[[1, 1],\n",
    "#[1, 1],   +     [0, 1, 2]\n",
    "#[1, 1]]\n",
    "M + a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 1.],\n",
       "       [2., 2.],\n",
       "       [3., 3.]])"
      ]
     },
     "execution_count": 100,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#解决：还记得newaxis吗？\n",
    "M + a[:, np.newaxis]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
